/*
 *  levelUpGame - GameModel.h
 *  Copyright 2011 W. Reckman. All rights reserved.
 */
#ifndef GAME_MODEL_H
#define GAME_MODEL_H

#include <vector>
#include "ofTypes.h"
#include "ofImage.h"
#include "BalanceMeter.h"
#include "Settings.h"
#include "Utils.h"

class LevelUpApp;
class Ghost;
class Pickup;
class Player;

/* Uncomment this define to disable spawning the ghosts. */
//#define DISABLE_GHOSTS


class GameModel {
public:
	//NOTE: PlayerInfo is declared here to avoid circular dependencies
	struct PlayerInfo {
		PlayerInfo()
		: topImagePath( 0 ), bottomImagePath( 0 )
		{}
		
		int month, day;
		int hours, minutes, seconds;
		int cultureTgt, industryTgt;
		int id;
		string* topImagePath;
		string* bottomImagePath;
		ofColor color;
		int goodPickups, badPickups;
	};
	
	bool p0Colliding; //TEMP
	
	enum NEAR_LANE { NL_PREV_X, NL_NEXT_X, NL_PREV_Y, NL_NEXT_Y };
	
	typedef std::vector<Player*> vec_PlayerP;
	typedef std::vector<Pickup*> vec_PickupP;
	typedef std::vector<int> vec_int;
	typedef std::vector<ofImage*> vec_ofImageP;
	
	static const int BALANCE_MAX;
	static const float PLAYER_IMAGE_DIMENSION_RATIO;
	static const float PLAYER_TOP_TO_TOTAL_RATIO;
	static const float LANE_THICKNESS;
	
	
	explicit GameModel( const LevelUpApp& appRef_ );
	~GameModel();
	
	void setup();
	void update();
	
	static const ofColor& getPlayerColor( int playerIdx_, PLAYER_COLOR_BRIGHTNESS brightness_ = PCB_NORMAL );
	
	float getTime() const;
	const vec_int& getRowLanes() const;
	const vec_int& getColumnLanes() const;
	const ofRectangle& getBoundingBox() const;
	const vec_PickupP& getPickups() const;
	vec_PickupP& getPickups();
	const vec_PlayerP& getPlayers() const;
	vec_PlayerP& getPlayers();
	const Player* getPlayer( int index_ ) const;
	Player* getPlayer( int index_ );
	const Ghost* getCultureGhost() const;
	Ghost* getCultureGhost();
	const Ghost* getIndustryGhost() const;
	Ghost* getIndustryGhost();
	const BalanceMeter& getBalanceMeter() const;
	BalanceMeter& getBalanceMeter();
	
	GAME_STATE getState() const;
	void setState( GAME_STATE state_ );
	
	bool isPaused() const;
	void setPaused( bool paused_ );
	
	int getBasePlayerSpeed() const;
	int getBaseGhostSpeed() const;
	int getBaseBiteSpeed() const;
	int getLaneWidth() const;
	int getMaxObjectWidth() const;
	int getStageLaneBottomY() const;
	int getPlayerYSubtract() const;
	int getBalanceStepPlayer() const;
	int getBalanceStepGlobal() const;
	int getMinPickupDistance() const;
	float getEndAnimScaleUp() const;
	
	void resetGhostPositions();
	
	bool isGamePlaying() const;
	float getGameDuration() const;
	float getPlayTimeLeft() const;
	void resetPlayTime();
	void resetBalance();
	
	float getPrecountTimeLeft() const;
	void runPrecount( float seconds_ );
	
	void showTimedText( const string& text_, float seconds_ );
	float getTimedTextLeft() const;
	const string& getTimedText() const;
	
	float getPanPosition( float x_ ) const;
	
	float calcPlayerScore( int playerId_ ) const;
	int getWinningPlayer() const;
	int determineWinner();
	
	const ofPoint& getPlayerDrawSize() const;
	int getMaxNumPlayers() const;
	
	bool setMaxNumPlayers( int maxNumPlayers_ );
	void addBalance( int val_, BALANCE_KIND kind_ );
	
	Player* createPlayer( const PlayerInfo& info_ );
	bool destroyPlayer( Player* p_ );
	bool spawnPickup( BALANCE_KIND balanceType );
	bool dirCoordsAreOnGrid( const ofPoint& c_, DIRECTION dir, int laneMargin_ = 0,
													int intersectMargin_ = 0, bool includeStageLanes_ = true,
													bool allowVerticalWrapping = true ) const;
	
	bool generateRandomPositionOnGrid( bool includeStageLanes_, ofPoint& pos_ ) const;
	
	int getNearLane( const GridPoint<int>& p_, NEAR_LANE which_, bool returnIndex_ ) const;
	bool fillInLaneIndices( GridPoint<int>& gp_, int laneMargin_, bool fixCoords_ = false ) const;
	
private:
	const Settings& s;
	const LevelUpApp& appRef;
	
	float gameTime;
	GAME_STATE gameState;
	vec_int lutRows, lutColumns;
	ofRectangle boundingBox;
	ofPoint playerDrawSize;
	
	vec_ofImageP culturePickupImages;
	vec_ofImageP industryPickupImages;
	
	bool paused;
	int maxNumPlayers;
	vec_PlayerP players;
	vec_PickupP pickups;
	Ghost* cultureGhost;
	Ghost* industryGhost;
	//Pickup* balancePickup;
	BalanceMeter balance;
	
	int basePlayerSpeed;
	int baseGhostSpeed;
	int baseBiteSpeed;
	int laneWidth;
	int maxObjectWidth;
	int stageLaneBottomY;
	float playerYSubtract;
	int balanceStepPlayer;
	int balanceStepGlobal;
	int minPickupDistance;
	float endAnimScaleUp;
	
	float gameDuration;
	float playTimeLeft;
	float precountTimeLeft;
	
	string timedText;
	float timedTextLeft;
	
	int winningPlayer;
	
	void initLookupTables();
	void initGhosts();
	void initPickupImages();
};

#endif /* ! GAME_MODEL_H */
